home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / hashsig / hashsig.lha / md4.c < prev    next >
C/C++ Source or Header  |  1993-08-09  |  12KB  |  362 lines

  1.  
  2. /* The following notices are copied from the original release
  3.  * of MD4 made available from Ron Rivest from MIT
  4.  */
  5. /*
  6. ___________________________________________________________________
  7. License to copy and use this document and the software described
  8. herein is granted provided it is identified as the "RSA Data
  9. Security, Inc. MD4 Message Digest Algorithm" in all materials
  10. mentioning or referencing this software, function, or document.
  11.  
  12. License is also granted to make derivative works provided that such
  13. works are identified as "derived from the RSA Data Security, Inc. MD4
  14. Message Digest Algorithm" in all material mentioning or referencing
  15. the derived work.
  16.  
  17. RSA Data Security, Inc. makes no representations concerning the
  18. merchantability of this algorithm or software or their suitability
  19. for any specific purpose.  It is provided "as is" without express or
  20. implied warranty of any kind.
  21.  
  22. These notices must be retained in any copies of any part of this
  23. documentation and/or software.
  24. ___________________________________________________________________
  25.  
  26.  * XEROX GRANTS NO DIFFERENT OR ADDITIONAL RIGHTS TO USE THE
  27.  * MODIFIED VERSION OF MD4 CONTAINED HEREIN.
  28.  */
  29.  
  30. /*
  31.  * Various minor modifications (which should not change
  32.  * the hash value computed) made 90.03.28 by Ralph C. Merkle
  33.  */
  34. typedef    unsigned long int    word32;
  35. void ErrAbort ();
  36. /*
  37.  * The following routine converts a byte array to an array of word32.
  38.  * This routine is intended for use with MD4, which defines
  39.  * byte-ordering in the little endian or VAX style.  This routine
  40.  * should work on almost any machine.  Non-portable routines should
  41.  * be significantly faster.
  42.  * Added 90.03.29 by Ralph C. Merkle.
  43.  */
  44. void 
  45. MD4ConvertBytes (buffer, wordBuffer, wordCount)
  46.     char    buffer[];    /*  input buffer */
  47.     word32 wordBuffer[];    /*  output buffer */
  48.     int     wordCount;
  49. {
  50.     int     i;
  51.     word32 t0, t1, t2, t3;
  52.  
  53.     for (i = 0; i < wordCount; i++) {
  54.         t0 = buffer[4 * i + 3];
  55.         t1 = buffer[4 * i + 2];
  56.         t2 = buffer[4 * i + 1];
  57.         t3 = buffer[4 * i + 0];
  58.         t0 &= 0xff;
  59.         t1 &= 0xff;
  60.         t2 &= 0xff;
  61.         t3 &= 0xff;
  62.         wordBuffer[i] = (t0 << 24) | (t1 << 16) | (t2 << 8) | t3;
  63.     };
  64. }
  65.  
  66. /* 
  67. ** **************************************************************************
  68. ** md4.c -- Implementation of MD4 Message Digest Algorithm                 **
  69. ** Updated: 2/16/90 by Ronald L. Rivest                                    **
  70. ** (C) 1990 RSA Data Security, Inc.                                        **
  71. ** **************************************************************************
  72. */
  73.  
  74. /* 
  75. ** To use MD4:
  76. **   -- Include md4.h in your program
  77. **   -- Declare an MDstruct MD to hold the state of the digest computation.
  78. **   -- Initialize MD using MDbegin(&MD)
  79. **   -- For each full block (64 bytes) X you wish to process, call
  80. **          MDupdate(&MD,X,512)
  81. **      (512 is the number of bits in a full block.)
  82. **   -- For the last block (less than 64 bytes) you wish to process,
  83. **          MDupdate(&MD,X,n)
  84. **      where n is the number of bits in the partial block. A partial
  85. **      block terminates the computation, so every MD computation should
  86. **      terminate by processing a partial block, even if it has n = 0.
  87. **   -- The message digest is available in MD.buffer[0] ... MD.buffer[3].
  88. **      (Least-significant byte of each word should be output first.)
  89. **   -- You can print out the digest using MDprint(&MD)
  90. */
  91.  
  92. /* Comment added 90.03.29 by RCM:  this implementation should be portable.
  93.  * This will result in some loss of speed.  The "MDreverse" routine
  94.  * provided by Rivest has been commented out, and the more portable
  95.  * "MD4ConvertBytes" has been added.
  96.  */
  97.  
  98. /* Compile-time includes 
  99. */
  100. #include <stdio.h>
  101. #include "md4.h"
  102.  
  103. /* Compile-time declarations of MD4 ``magic constants''.
  104. */
  105. #define I0  0x67452301L       /* Initial values for MD buffer */
  106. #define I1  0xefcdab89L
  107. #define I2  0x98badcfeL
  108. #define I3  0x10325476L
  109. #define C2  013240474631L     /* round 2 constant = sqrt(2) in octal */
  110. #define C3  015666365641L     /* round 3 constant = sqrt(3) in octal */
  111. /* C2 and C3 are from Knuth, The Art of Programming, Volume 2
  112. ** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
  113. ** Table 2, page 660.
  114. */
  115. #define fs1  3               /* round 1 shift amounts */
  116. #define fs2  7   
  117. #define fs3 11  
  118. #define fs4 19  
  119. #define gs1  3               /* round 2 shift amounts */
  120. #define gs2  5   
  121. #define gs3  9   
  122. #define gs4 13  
  123. #define hs1  3               /* round 3 shift amounts */
  124. #define hs2  9 
  125. #define hs3 11 
  126. #define hs4 15
  127.  
  128.  
  129. /* Compile-time macro declarations for MD4.
  130. ** Note: The ``rot'' operator uses the variable ``tmp''.
  131. ** It assumes tmp is declared as word32, so that the >>
  132. ** operator will shift in zeros rather than extending the sign bit.
  133. */
  134. #define    f(X,Y,Z)             ((X&Y) | ((~X)&Z))
  135. #define    g(X,Y,Z)             ((X&Y) | (X&Z) | (Y&Z))
  136. #define h(X,Y,Z)             (X^Y^Z)
  137. #define rot(X,S)             (tmp=X,(tmp<<S) | (tmp>>(32-S)))
  138. #define ff(A,B,C,D,i,s)      A = rot((A + f(B,C,D) + X[i]),s)
  139. #define gg(A,B,C,D,i,s)      A = rot((A + g(B,C,D) + X[i] + C2),s)
  140. #define hh(A,B,C,D,i,s)      A = rot((A + h(B,C,D) + X[i] + C3),s)
  141.  
  142. /* MDprint(MDp)
  143. ** Print message digest buffer MDp as 32 hexadecimal digits.
  144. ** Order is from low-order byte of buffer[0] to high-order byte of buffer[3].
  145. ** Each byte is printed with high-order hexadecimal digit first.
  146. ** This is a user-callable routine.
  147. */
  148. /*
  149. void 
  150. MDprint(MDp)
  151. MDptr MDp;
  152. { int i,j;
  153.   for (i=0;i<4;i++)
  154.     for (j=0;j<32;j=j+8)
  155.       printf("%02x",(MDp->buffer[i]>>j) & 0xFFL);
  156. }
  157. */
  158. /* MDbegin(MDp)
  159. ** Initialize message digest buffer MDp. 
  160. ** This is a user-callable routine.
  161. */
  162. void 
  163. MDbegin(MDp)
  164. MDptr MDp;
  165. { int i;
  166.   MDp->buffer[0] = I0;  
  167.   MDp->buffer[1] = I1;  
  168.   MDp->buffer[2] = I2;  
  169.   MDp->buffer[3] = I3; 
  170.   for (i=0;i<8;i++) MDp->count[i] = 0;
  171.   MDp->done = 0;
  172. }
  173.  
  174. /* MDreverse(X)
  175. ** Reverse the byte-ordering of every int in X.
  176. ** Assumes X is an array of 16 ints.
  177. ** The macro revx reverses the byte-ordering of the next word of X.
  178. */
  179. /*
  180. #define revx { t = (*X << 16) | (*X >> 16); \
  181.            *X++ = ((t & 0xFF00FF00L) >> 8) | ((t & 0x00FF00FFL) << 8); }
  182. MDreverse(X)
  183. word32 *X;
  184. { register word32 t;
  185.   revx; revx; revx; revx; revx; revx; revx; revx;
  186.   revx; revx; revx; revx; revx; revx; revx; revx;
  187. }
  188. */
  189.  
  190. /* MDblock(MDp,X)
  191. ** Update message digest buffer MDp->buffer using 16-word data block X.
  192. ** Assumes all 16 words of X are full of data.
  193. ** Does not update MDp->count.
  194. ** This routine is not user-callable. 
  195. */
  196. static void
  197. MDblock(MDp,charX)
  198. MDptr MDp;
  199. char *charX;
  200. {
  201.   word32 X[16];
  202.   register word32 tmp, A, B, C, D;
  203.   MD4ConvertBytes(charX, X, 16);
  204.   A = MDp->buffer[0];
  205.   B = MDp->buffer[1];
  206.   C = MDp->buffer[2];
  207.   D = MDp->buffer[3];
  208.   /* Update the message digest buffer */
  209.   ff(A , B , C , D ,  0 , fs1); /* Round 1 */
  210.   ff(D , A , B , C ,  1 , fs2); 
  211.   ff(C , D , A , B ,  2 , fs3); 
  212.   ff(B , C , D , A ,  3 , fs4); 
  213.   ff(A , B , C , D ,  4 , fs1); 
  214.   ff(D , A , B , C ,  5 , fs2); 
  215.   ff(C , D , A , B ,  6 , fs3); 
  216.   ff(B , C , D , A ,  7 , fs4); 
  217.   ff(A , B , C , D ,  8 , fs1); 
  218.   ff(D , A , B , C ,  9 , fs2); 
  219.   ff(C , D , A , B , 10 , fs3); 
  220.   ff(B , C , D , A , 11 , fs4); 
  221.   ff(A , B , C , D , 12 , fs1); 
  222.   ff(D , A , B , C , 13 , fs2); 
  223.   ff(C , D , A , B , 14 , fs3); 
  224.   ff(B , C , D , A , 15 , fs4); 
  225.   gg(A , B , C , D ,  0 , gs1); /* Round 2 */
  226.   gg(D , A , B , C ,  4 , gs2); 
  227.   gg(C , D , A , B ,  8 , gs3); 
  228.   gg(B , C , D , A , 12 , gs4); 
  229.   gg(A , B , C , D ,  1 , gs1); 
  230.   gg(D , A , B , C ,  5 , gs2); 
  231.   gg(C , D , A , B ,  9 , gs3); 
  232.   gg(B , C , D , A , 13 , gs4); 
  233.   gg(A , B , C , D ,  2 , gs1); 
  234.   gg(D , A , B , C ,  6 , gs2); 
  235.   gg(C , D , A , B , 10 , gs3); 
  236.   gg(B , C , D , A , 14 , gs4); 
  237.   gg(A , B , C , D ,  3 , gs1); 
  238.   gg(D , A , B , C ,  7 , gs2); 
  239.   gg(C , D , A , B , 11 , gs3); 
  240.   gg(B , C , D , A , 15 , gs4);  
  241.   hh(A , B , C , D ,  0 , hs1); /* Round 3 */
  242.   hh(D , A , B , C ,  8 , hs2); 
  243.   hh(C , D , A , B ,  4 , hs3); 
  244.   hh(B , C , D , A , 12 , hs4); 
  245.   hh(A , B , C , D ,  2 , hs1); 
  246.   hh(D , A , B , C , 10 , hs2); 
  247.   hh(C , D , A , B ,  6 , hs3); 
  248.   hh(B , C , D , A , 14 , hs4); 
  249.   hh(A , B , C , D ,  1 , hs1); 
  250.   hh(D , A , B , C ,  9 , hs2); 
  251.   hh(C , D , A , B ,  5 , hs3); 
  252.   hh(B , C , D , A , 13 , hs4); 
  253.   hh(A , B , C , D ,  3 , hs1); 
  254.   hh(D , A , B , C , 11 , hs2); 
  255.   hh(C , D , A , B ,  7 , hs3); 
  256.   hh(B , C , D , A , 15 , hs4);
  257.   MDp->buffer[0] += A; 
  258.   MDp->buffer[1] += B;
  259.   MDp->buffer[2] += C;
  260.   MDp->buffer[3] += D; 
  261. }
  262.  
  263. /* MDupdate(MDp,X,count)
  264. ** Input: MDp -- an MDptr
  265. **        X -- a pointer to an array of unsigned characters.
  266. **        count -- the number of bits of X to use.
  267. **                 (if not a multiple of 8, uses high bits of last byte.)
  268. ** Update MDp using the number of bits of X given by count.
  269. ** This is the basic input routine for an MD4 user.
  270. ** The routine completes the MD computation when count < 512, so
  271. ** every MD computation should end with one call to MDupdate with a
  272. ** count less than 512.  A call with count 0 will be ignored if the
  273. ** MD has already been terminated (done != 0), so an extra call with count
  274. ** 0 can be given as a ``courtesy close'' to force termination if desired.
  275. */
  276. void 
  277. MDupdate(MDp,X,count)
  278. MDptr MDp;
  279. char *X;
  280. int count;
  281. { word32 i, tmp, bit, byte, mask;
  282.   char XX[64];
  283.   unsigned char *p;
  284.   /* return with no error if this is a courtesy close with count
  285.   ** zero and MDp->done is true.
  286.   */
  287.   if (count == 0 && MDp->done) return;
  288.   /* check to see if MD is already done and report error */
  289.   if (MDp->done) {
  290.     fprintf(stderr, "\nError: MDupdate MD already done.");
  291.     exit(1);
  292.   }
  293.   /* Add count to MDp->count */
  294.   tmp = count;
  295.   p = MDp->count;
  296.   while (tmp)
  297.     { tmp += *p;
  298.       *p++ = tmp;
  299.       tmp = tmp >> 8;
  300.     }
  301.   /* Process data */
  302.   if (count == 512) 
  303.     { /* Full block of data to handle */
  304.       MDblock(MDp,X);
  305.     }
  306.   else if (count > 512) /* Check for count too large */
  307.     { fprintf(stderr,
  308.     "\nError: MDupdate called with illegal count value %d.",count);
  309.       exit(1);
  310.     }
  311.   else /* partial block -- must be last block so finish up */
  312.     { /* Find out how many bytes and residual bits there are */
  313.       byte = count >> 3;
  314.       bit =  count & 7;
  315.       /* Copy X into XX since we need to modify it */
  316.       for (i=0;i<=byte;i++)   XX[i] = X[i];
  317.       for (i=byte+1;i<64;i++) XX[i] = 0;
  318.       /* Add padding '1' bit and low-order zeros in last byte */
  319.       mask = 1 << (7 - bit);
  320.       XX[byte] = (XX[byte] | mask) & ~( mask - 1);
  321.       /* If room for bit count, finish up with this block */
  322.       if (byte <= 55)
  323.         { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
  324.           MDblock(MDp,XX);
  325.         }
  326.       else /* need to do two blocks to finish up */
  327.         { MDblock(MDp,XX);
  328.           for (i=0;i<56;i++) XX[i] = 0;
  329.           for (i=0;i<8;i++)  XX[56+i] = MDp->count[i];
  330.           MDblock(MDp,XX);
  331.         }
  332.       /* Set flag saying we're done with MD computation */
  333.       MDp->done = 1;
  334.     }
  335. }
  336.  
  337. /* The following routine was adapted from the routine provided by
  338.  * Ron Rivest. It computes the message digest for a specified file.
  339.  */
  340. Md4HashFile(inputFile, hashValue, hashValueSize)
  341.     FILE    *inputFile;
  342.     word32    hashValue[];
  343.     int    hashValueSize;
  344. {    char    X[64];
  345.     MDstruct    MD;
  346.     int    b;
  347.  
  348.     if (hashValueSize != 4)
  349.         ErrAbort("Only implemented 128-bit output for MD4");
  350.     MDbegin(&MD);
  351.     while ((b=fread(X,1,64,inputFile))!=0)
  352.         MDupdate(&MD,X,b*8);
  353.     if (ferror(inputFile))
  354.         ErrAbort("Can't read from input file");
  355.     MDupdate(&MD,X,0);
  356.     hashValue[0] = MD.buffer[0];
  357.     hashValue[1] = MD.buffer[1];
  358.     hashValue[2] = MD.buffer[2];
  359.     hashValue[3] = MD.buffer[3];
  360. }
  361.  
  362.